from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from bson import ObjectId

class PyObjectId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if not ObjectId.is_valid(v):
            raise ValueError("无效的ObjectId")
        return ObjectId(v)

    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")

# 数据库配置设置的基础模型
class DBInfoSettingBase(BaseModel):
    db_type: Optional[str] = Field(None, description="数据库类型 (mysql, sqlserver, fabric_sqlserver)")
    connection_name: Optional[str] = Field(None, description="连接名称")
    host: Optional[str] = Field(None, description="数据库主机地址")
    port: Optional[str] = Field(None, description="数据库端口")
    username: Optional[str] = Field(None, description="数据库用户名")
    password: Optional[str] = Field(None, description="数据库密码")
    database_name: Optional[str] = Field(None, description="数据库名称")
    connection_string_ext: Optional[str] = Field(None, description="额外的连接字符串参数")

# 创建新数据库连接设置的模型
class DBInfoSettingCreate(DBInfoSettingBase):
    id: Optional[str] = Field(None, description="数据库连接设置ID")
    pass

# 更新现有数据库连接设置的模型
class DBInfoSettingUpdate(BaseModel):
    db_type: Optional[str] = None
    connection_name: Optional[str] = None
    host: Optional[str] = None
    port: Optional[str] = None
    username: Optional[str] = None
    password: Optional[str] = None
    database_name: Optional[str] = None
    connection_string_ext: Optional[str] = None

# 数据库中的数据库连接设置模型
class DBInfoSettingInDB(DBInfoSettingBase):
    id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
    created_at: datetime = Field(default_factory=datetime.now)
    created_by: str = Field(default="system")
    updated_at: Optional[datetime] = None
    updated_by: Optional[str] = None

    class Config:
        allow_population_by_field_name = True
        arbitrary_types_allowed = True
        json_encoders = {
            ObjectId: str,
            datetime: lambda dt: dt.isoformat()
        }

# 数据库连接设置响应模型
class DBInfoSetting(DBInfoSettingInDB):
    pass

# 数据库连接测试模型
class DBConnectionTest(DBInfoSettingBase):
    pass

# API端点的响应模型
class ResponseModel(BaseModel):
    code: int = Field(200, description="响应代码")
    data: Optional[dict] = Field(None, description="响应数据")
    message: str = Field("成功", description="响应消息")
    timestamp: str = Field(..., description="响应时间戳")

# 列表响应模型
class DBInfoSettingListResponse(BaseModel):
    code: int = 200
    data: List[DBInfoSetting]
    message: str = "成功"
    timestamp: str

# 单项响应模型
class DBInfoSettingResponse(BaseModel):
    code: int = 200
    data: Optional[DBInfoSetting] = None
    message: str = "成功"
    timestamp: str